#define GLEW_STATIC
#include "GL\glew.h"
#include "GL\wglew.h"
#define FREEGLUT_STATIC
#include "GL\freeglut.h"
#include "GLTools.h"
#include "GLShaderManager.h"
#include "StopWatch.h"
#include <cstdio>

GLBatch squareBatch;
GLShaderManager shaderManager;
CStopWatch watch;
float time;
char buffer[256];
int frames = 1;

GLfloat blockSize = 0.1;
GLfloat vVerts[] = { -blockSize,-blockSize,0.0,
					blockSize,-blockSize,0.0,
					blockSize,blockSize,0.0,
					-blockSize,blockSize,0.0};
void ChangeSize(int w, int h)
{
	glViewport(0, 0, w, h);
}

void SetupRC()
{

	// Blue background
	glClearColor(1.0f, 1.0f, 1.0f, 1.0f );
	shaderManager.InitializeStockShaders();
	// Load up a triangle
	squareBatch.Begin(GL_TRIANGLE_FAN, 4);
	squareBatch.CopyVertexData3f(vVerts);
	squareBatch.End();
	watch.Reset();
}

void SpecialKeys(int key,int x,int y)
{
	GLfloat stepSize = 0.025;

	GLfloat blockX = vVerts[0];
	GLfloat blockY = vVerts[7];

	if (key == GLUT_KEY_UP)
		blockY+=stepSize;

	if(key ==GLUT_KEY_DOWN)
		blockY-=stepSize;

	if (key ==GLUT_KEY_LEFT)
		blockX-=stepSize;

	if(key==GLUT_KEY_RIGHT)
		blockX+=stepSize;

	if (blockX < -1.0) blockX=-1.0;
	if (blockX >(1.0-blockSize*2)) blockX = 1.0 - blockSize*2;
	if(blockY >1.0) blockY = 1.0;
	if(blockY <(-1.0 + 2*blockSize)) blockY = - 1.0 + blockSize*2;


	vVerts[0] = blockX;
	vVerts[1] = blockY - 2*blockSize;

	vVerts[3] = blockX + 2*blockSize;
	vVerts[4] = blockY - 2*blockSize;

	vVerts[6] = blockX + 2*blockSize;
	vVerts[7] = blockY;

	vVerts[9] = blockX;
	vVerts[10] = blockY;

	squareBatch.CopyVertexData3f(vVerts);

	glutPostRedisplay();
}


void RenderScene(void)
{
	
	// Clear the window with current clearing color
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
	GLfloat vRed[] = { 1.0f, 0.0f, 0.0f, 1.0f };
	shaderManager.UseStockShader(GLT_SHADER_IDENTITY, vRed);
	squareBatch.Draw();
	// Perform the buffer swap to display the back buffer
	glutSwapBuffers();

	++frames;

	if(frames == 60)
	{
		time = watch.GetElapsedSeconds();
		sprintf(buffer,"%f FPS",60.0/time);
		watch.Reset();
		frames = 1;
		::glutSetWindowTitle(buffer);
	}
	glutPostRedisplay();
}

int main(int argc, char* argv[])
{
	gltSetWorkingDirectory(argv[0]);
	glutInit(&argc, argv);
	glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH | GLUT_STENCIL);
	glutInitWindowSize(800, 800);
	glutCreateWindow("Triangle of death");
	glutReshapeFunc(ChangeSize);
	glutDisplayFunc(RenderScene);
	glutSpecialFunc(SpecialKeys);

	GLenum err = glewInit();
	if (GLEW_OK != err) {
		fprintf(stderr, "GLEW Error: %s\n", glewGetErrorString(err));
		return 1;
	}
	SetupRC();
	glutMainLoop();
	return 0;
}